package com.orange.lockscreen.layers.slider;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;

import com.orange.lockscreen.R;
import com.orange.lockscreen.SlatHashMap;
import com.orange.lockscreen.anims.LCTranslateAnimation;
import com.orange.lockscreen.anims.LCTranslateAnimation.OnTranslateListener;
import com.orange.lockscreen.common.Constants;
import com.orange.lockscreen.common.LogHelper;
import com.orange.lockscreen.layers.GenericSlat;

public class SliderSlat extends GenericSlat implements OnTranslateListener {

	private static final String		TAG						= "SliderSlat";

	private ImageView				mDimmerView				= null;
	private ImageView				mSnapshotView			= null;
	private ImageView				mRightShadowView		= null;
	private ImageView				mLeftShadowView			= null;

	private Bitmap					mSnapshotBitmap			= null;
	private Drawable				mDimDrawable			= null;

	private int						mSlatType				= TYPE_FIXED;
	private boolean					mIsClosed				= true;
	private boolean					mIsDocked				= false;

	private boolean					mIsSelected				= false;

	private boolean					mIsNotifyVibrator		= false;

	private boolean					mIsGoDocked				= false;
	private boolean					mIsAnimating			= false;
	private boolean					mIsSelfForceGo			= false;

	private int						mRowIndex				= 0;

	private OnSliderMotionListener	mSliderMotionListener	= null;

	private LayoutParams			mLayoutParams			= null;

	private Runnable				mRunnable				= null;

	private int						mDockWidth;

	public SliderSlat(Context context) {
		super(context);
		mRowIndex = SlatHashMap.MUSIC_WIDGET_ROWINDEX;
		mDockWidth = (int) getResources()
				.getDimension(R.dimen.music_dock_width);
		init();
	}

	protected void init() {
		mLayoutParams = new LayoutParams();
		setLayoutParams(mLayoutParams);

		LayoutInflater inflater = LayoutInflater.from(getContext());
		View viewGroup = inflater.inflate(R.layout.layout_slider_slat, this,
				true);
		mDimmerView = (ImageView) viewGroup
				.findViewById(R.id.layout_slider_slat_dimmer);
		mSnapshotView = (ImageView) viewGroup
				.findViewById(R.id.layout_slider_slat_snapshot);
		mRightShadowView = (ImageView) viewGroup
				.findViewById(R.id.layout_slider_slat_right_shadow);
		mLeftShadowView = (ImageView) viewGroup
				.findViewById(R.id.layout_slider_slat_left_shadow);

		this.setVisibility(INVISIBLE);
	}

	public void setOnSliderMotionLisenter(OnSliderMotionListener listener) {
		mSliderMotionListener = listener;
	}

	public int getSlatType() {
		return mSlatType;
	}

	public void move(int xOffset) {

		if (!mIsSelected && !mIsSelfForceGo) {
			return;
		}

		int orientation = SlatHashMap.getHandlerOrientation();

		if (mIsClosed && xOffset < 0
				&& SlatHashMap.getHandlerOrientation() == LEFT_TO_RIGHT) {
			return;
		}

		LayoutParams lp = mLayoutParams;
		int offset = lp.xHistoryOffset + xOffset;

		if (offset <= 0) {
			mIsClosed = true;
			lp.xOffset = 0;
		} else {
			mIsClosed = false;
			lp.xOffset = offset;
		}

		int offsetAbs = Math.abs(lp.xOffset);

		int dockWidth = (mSlatType == TYPE_UNLOCK || mSlatType == TYPE_MOVABLE_UNLOCK) ? Constants.UNLOCK_DOCK_WIDTH : mDockWidth;

		if (offsetAbs > 0 && (offsetAbs < lp.width / 3 - dockWidth)) {
			mIsNotifyVibrator = false;
		} else if (offsetAbs == 0) {
			if (!mIsNotifyVibrator) {
				mSliderMotionListener.onSliderHitBroad(mRowIndex);
				mIsNotifyVibrator = true;
			}
			if (!mIsSelected) {
				mSliderMotionListener.onSliderClosed(mRowIndex);
			}
		} else {
			if (orientation == LEFT_TO_RIGHT) {
				lp.xOffset = lp.width / 3 - dockWidth;
			} else {
				lp.xOffset = dockWidth - lp.width / 3;
			}
			if (!mIsNotifyVibrator) {
				mSliderMotionListener.onSliderOpened(mRowIndex);
				mIsNotifyVibrator = true;
			}
		}

		dimEffect(offsetAbs);

		if (mSliderMotionListener != null) {
			mSliderMotionListener.onSliderMoving(mRowIndex, lp.xOffset);
		}
	}

	private boolean checkOverBoundary(int offsetAbs) {
		boolean isOver = false;
		LayoutParams lp = mLayoutParams;
		int width = lp.width / 3;
		if ((width - offsetAbs) <= Constants.UNLOCK_DOCK_WIDTH) {
			isOver = true;
		} else {
			isOver = false;
		}
		return isOver;
	}

	public void autoRollBack() {
		LayoutParams lp = mLayoutParams;
		int offsetAbs = Math.abs(lp.xHistoryOffset);
		int width = lp.width / 3;
		int dockWidth = (mSlatType == TYPE_UNLOCK || mSlatType == TYPE_MOVABLE_UNLOCK) ? Constants.UNLOCK_DOCK_WIDTH : mDockWidth;
		if (!mIsDocked && (width - offsetAbs == dockWidth)) {
			mIsDocked = true;
			return;
		}
		if (offsetAbs > 0 && mSlatType == TYPE_MOVABLE) {
			startAnimation();
		} else {
			mIsGoDocked = false;
			onAnimationEnd();
		}
	}

	private void startAnimation() {
		if (!isShown()) {
			setVisibility(VISIBLE);
		}
		LCTranslateAnimation animation = null;
		int distance = 0;
		LayoutParams lp = mLayoutParams;
		int offsetAbs = Math.abs(lp.xHistoryOffset);
		int width = lp.width / 3;
		int type = mSlatType & TYPE_UNLOCK;
		if (!mIsDocked && checkOverBoundary(offsetAbs) && offsetAbs > width / 2
				&& (type != TYPE_UNLOCK)) {
			distance = width - offsetAbs - mDockWidth;
			mIsGoDocked = true;
		} else {
			distance = -lp.xHistoryOffset;
			mIsGoDocked = false;
			mIsNotifyVibrator = false;
		}
		long durationMillis = Math.abs(distance) * Constants.ANIMATION_DURATION
				/ width;
		animation = new LCTranslateAnimation(0, distance, 0, 0);
		animation.setOnTranslateListener(this);
		animation.setDuration(durationMillis);
		animation.setInterpolator(new DecelerateInterpolator());
		startAnimation(animation);
		mIsAnimating = true;
		LogHelper.v(TAG, "startAnimation. ");
	}

	public void setSnapshot(Bitmap bitmap) {
		mSnapshotBitmap = bitmap;
		mSnapshotView.setBackgroundDrawable(new BitmapDrawable(bitmap));
	}

	public void clearSnapshot() {
		mSnapshotView.setBackgroundDrawable(null);
		if (null != mSnapshotBitmap) {
			mSnapshotBitmap.recycle();
		}
	}

	public void release() {
		clearSnapshot();
		mDimmerView.setBackgroundDrawable(null);
		mDimDrawable = null;
		mLeftShadowView.setBackgroundDrawable(null);
		mRightShadowView.setBackgroundDrawable(null);
	}

	public void setSelected(boolean isSelected) {
		mIsSelected = isSelected;
		if (!isSelected) {
			mLayoutParams.xHistoryOffset = mLayoutParams.xOffset;
		} else {
			mSlatType = SlatHashMap.getSlatType(mRowIndex);
			mIsSelfForceGo = false;
		}
	}

	public boolean isDocked() {
		return mIsDocked;
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		LogHelper.v(TAG, "onLayout. rowIndex=" + mRowIndex + " changed="
				+ changed);

		int width = (r - l) / 3;
		int height = b - t;
		mDimmerView.layout(0, 0, width, height);
		mSnapshotView.layout(width, 0, 2 * width, height);
		mRightShadowView.layout(2 * width, 0, 3 * width, height);
		mLeftShadowView.layout(0, 0, width, height);
	}

	public boolean isAnimating() {
		return mIsAnimating;
	}

	public void setAnimationEnd() {
		mIsAnimating = false;
		if (mRunnable != null) {
			this.post(mRunnable);
		}
	}

	@Override
	protected void onAnimationEnd() {
		LogHelper.v(TAG, "onAnimationEnd. ");
		super.onAnimationEnd();
		restoreSlat();
		// mIsAnimating = false;
	}

	@Override
	protected void onAnimationStart() {
		LogHelper.v(TAG, "onAnimationStart. ");
		super.onAnimationStart();
	}

	private void restoreSlat() {
		LayoutParams lp = mLayoutParams;
		if (mIsGoDocked) {
			lp.xHistoryOffset = lp.width / 3 - mDockWidth;
			mIsSelfForceGo = true;
			move(lp.xHistoryOffset);
			mIsDocked = true;
		} else {
			lp.xHistoryOffset = 0;
			mIsSelfForceGo = true;
			move(0);
			mIsClosed = true;
			mIsDocked = false;
		}
	}

	public void setRunnable() {
		if (mRunnable != null) {
			mRunnable = null;
		}
		mRunnable = new Runnable() {
			@Override
			public void run() {
				autoRollBack();
				mRunnable = null;
			}
		};
	}

	private void dimEffect(int xOffset) {

		if (null == mDimDrawable) {
			mDimDrawable = mDimmerView.getDrawable();
		}
		int halfOfWidth = mLayoutParams.width / 6;

		if (xOffset > halfOfWidth) {
			xOffset = halfOfWidth;
		}

		int type = mSlatType & TYPE_UNLOCK;
		int alphaOffset = type == TYPE_UNLOCK ? Constants.DIM_OPACITY_OFFSET : 0;

		int alpha = (int) (((halfOfWidth - xOffset) / (float) halfOfWidth)
				* (Constants.DIM_OPACITY - alphaOffset) + alphaOffset);

		mDimDrawable.setAlpha(alpha);
	}

	@Override
	public void onTranslate(float dx, float dy) {
		int offset = (int) Math.abs(dx + mLayoutParams.xHistoryOffset);
		dimEffect(offset);
		mDimmerView.invalidate();

		if (mSliderMotionListener != null) {
			mSliderMotionListener.onSliderMoving(mRowIndex, offset);
		}

		LogHelper.v(TAG, "onTranslate. isAnimation=" + isAnimating()
				+ " isShown=" + isShown());
	}

	public interface OnSliderMotionListener {
		void onSliderOpened(int rowIndex);

		void onSliderClosed(int rowIndex);

		void onSliderHitBroad(int rowIndex);

		void onSliderMoving(int rowIndex, int xOffset);
	}
}
